// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef GPU_COMMAND_BUFFER_SERVICE_DECODER_CONTEXT_H_
#define GPU_COMMAND_BUFFER_SERVICE_DECODER_CONTEXT_H_

#include <stddef.h>
#include <stdint.h>

#include <string>

#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "build/build_config.h"
#include "gpu/command_buffer/common/capabilities.h"
#include "gpu/command_buffer/common/constants.h"
#include "gpu/command_buffer/common/context_result.h"
#include "gpu/command_buffer/service/abstract_texture.h"
#include "gpu/command_buffer/service/async_api_interface.h"
#include "gpu/command_buffer/service/gl_context_virtual_delegate.h"
#include "gpu/gpu_gles2_export.h"
#include "ui/gfx/geometry/rect.h"

namespace gl {
class GLContext;
class GLImage;
class GLSurface;
}  // namespace gl

namespace gpu {
class TextureBase;
struct ContextCreationAttribs;

namespace gles2 {
class ContextGroup;
class ErrorState;
class FeatureInfo;
class GpuFenceManager;
class Outputter;
class Texture;
struct DisallowedFeatures;
}  // namespace gles2

// Abstract interface implemented by {Raster,GLES2}Decoder. It is called a
// DecoderContext because all methods are about decoding commands or
// accessing context/state generated by decoded commands.
class GPU_GLES2_EXPORT DecoderContext : public AsyncAPIInterface,
                                        public GLContextVirtualDelegate {
 public:
  DecoderContext() = default;
  ~DecoderContext() override = default;

  //
  // Methods required by CommandBufferStub.
  //
  // Initializes the graphics context. Can create an offscreen
  // decoder with a frame buffer that can be referenced from the parent.
  // Takes ownership of GLContext.
  // Parameters:
  //  surface: the GL surface to render to.
  //  context: the GL context to render to.
  //  offscreen: whether to make the context offscreen or not. When FBO 0 is
  //      bound, offscreen contexts render to an internal buffer, onscreen ones
  //      to the surface.
  //  offscreen_size: the size if the GL context is offscreen.
  // Returns:
  //   true if successful.
  virtual gpu::ContextResult Initialize(
      const scoped_refptr<gl::GLSurface>& surface,
      const scoped_refptr<gl::GLContext>& context,
      bool offscreen,
      const gles2::DisallowedFeatures& disallowed_features,
      const ContextCreationAttribs& attrib_helper) = 0;

  // Destroys the graphics context.
  virtual void Destroy(bool have_context) = 0;

  virtual Capabilities GetCapabilities() = 0;

  virtual const gles2::FeatureInfo* GetFeatureInfo() const = 0;

  // Gets the associated GLContext.
  virtual gl::GLContext* GetGLContext() = 0;

  // Gets the associated GLSurface.
  virtual gl::GLSurface* GetGLSurface() = 0;

  // Make this decoder's GL context current.
  virtual bool MakeCurrent() = 0;

  // Lose this context.
  virtual void MarkContextLost(error::ContextLostReason reason) = 0;

  // Returns true if the context was lost either by GL_ARB_robustness, forced
  // context loss or command buffer parse error.
  virtual bool WasContextLost() const = 0;

  // Returns true if the context was lost specifically by GL_ARB_robustness.
  virtual bool WasContextLostByRobustnessExtension() const = 0;

  // Updates context lost state and returns true if lost. Most callers can use
  // WasContextLost() as the GLES2Decoder will update the state internally. But
  // if making GL calls directly, to the context then this state would not be
  // updated and the caller can use this to determine if their calls failed due
  // to context loss.
  virtual bool CheckResetStatus() = 0;

  // Set a callback to be called when a query is complete.  If the query is
  // invalid, the callback must be called immediately.
  virtual void SetQueryCallback(unsigned int query_client_id,
                                base::OnceClosure callback) = 0;

  // Gets the GpuFenceManager for this context.
  virtual gles2::GpuFenceManager* GetGpuFenceManager() = 0;

  // Returns false if there are no pending queries.
  virtual bool HasPendingQueries() const = 0;

  // Process any pending queries.
  virtual void ProcessPendingQueries(bool did_finish) = 0;

  // Returns false if there is no idle work to be made.
  virtual bool HasMoreIdleWork() const = 0;

  // Perform any idle work that needs to be made.
  virtual void PerformIdleWork() = 0;

  // Whether there is state that needs to be regularly polled.
  virtual bool HasPollingWork() const = 0;

  // Perform necessary polling.
  virtual void PerformPollingWork() = 0;

  //
  // Methods required by GpuVideoDecodeAccelerator.
  //
  // Gets the texture object associated with the client ID.  null is returned on
  // failure or if the texture has not been bound yet.
  virtual TextureBase* GetTextureBase(uint32_t client_id) = 0;
  virtual void SetLevelInfo(uint32_t client_id,
                            int level,
                            unsigned internal_format,
                            unsigned width,
                            unsigned height,
                            unsigned depth,
                            unsigned format,
                            unsigned type,
                            const gfx::Rect& cleared_rect) = 0;

#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE)
  // Attaches |image| to the texture referred to by |client_texture_id|, marking
  // the image as needing on-demand binding by the decoder.
  virtual void AttachImageToTextureWithDecoderBinding(
      uint32_t client_texture_id,
      uint32_t texture_target,
      gl::GLImage* image) = 0;
#elif !BUILDFLAG(IS_ANDROID)
  // Attaches |image| to the texture referred to by |client_texture_id|, marking
  // the image as not needing on-demand binding by the decoder.
  virtual void AttachImageToTextureWithClientBinding(uint32_t client_texture_id,
                                                     uint32_t texture_target,
                                                     gl::GLImage* image) = 0;
#endif
  virtual base::WeakPtr<DecoderContext> AsWeakPtr() = 0;

  //
  // Methods required by GLES2DecoderHelper.
  // Only functional for GLES2 Decoders.
  //
  virtual gles2::ContextGroup* GetContextGroup() = 0;
  virtual gles2::ErrorState* GetErrorState() = 0;
#if !(BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_OHOS))
  virtual std::unique_ptr<gpu::gles2::AbstractTexture> CreateAbstractTexture(
      unsigned /* GLenum */ target,
      unsigned /* GLenum */ internal_format,
      int /* GLsizei */ width,
      int /* GLsizei */ height,
      int /* GLsizei */ depth,
      int /* GLint */ border,
      unsigned /* GLenum */ format,
      unsigned /* GLenum */ type) = 0;
#endif

  //
  // Methods required by Texture.
  //
  // Indicates whether a given internal format is one for a compressed
  // texture.
  virtual bool IsCompressedTextureFormat(unsigned format) = 0;
  // Clears a level sub area of a 2D texture.
  // Returns false if a GL error should be generated.
  virtual bool ClearLevel(gles2::Texture* texture,
                          unsigned target,
                          int level,
                          unsigned format,
                          unsigned type,
                          int xoffset,
                          int yoffset,
                          int width,
                          int height) = 0;
  // Clears a level sub area of a compressed 2D texture.
  // Returns false if a GL error should be generated.
  virtual bool ClearCompressedTextureLevel(gles2::Texture* texture,
                                           unsigned target,
                                           int level,
                                           unsigned format,
                                           int width,
                                           int height) = 0;
  // Clears a level sub area of a compressed 3D texture.
  // Returns false if a GL error should be generated.
  virtual bool ClearCompressedTextureLevel3D(gles2::Texture* texture,
                                             unsigned target,
                                             int level,
                                             unsigned format,
                                             int width,
                                             int height,
                                             int depth) = 0;
  // Clears a level of a 3D texture.
  // Returns false if a GL error should be generated.
  virtual bool ClearLevel3D(gles2::Texture* texture,
                            unsigned target,
                            int level,
                            unsigned format,
                            unsigned type,
                            int width,
                            int height,
                            int depth) = 0;

  //
  // Methods required by InProcessCommandBuffer
  //
  // Set to true to LOG every command.
  virtual void SetLogCommands(bool log_commands) = 0;

  //
  // Methods required by GpuTracer
  //
  virtual gles2::Outputter* outputter() const = 0;

  // Restores all attributs in the gl context state.
  virtual void RestoreAllAttributes() const = 0;

  // Restores texture states for a given service id.
  virtual void RestoreTextureState(unsigned service_id) = 0;

  //
  // Methods required by ImageDecodeAcceleratorStub
  //
  // Returns the ID of a RasterDecoder. This is not applicable to other
  // implementations and it returns a negative number in that case.
  virtual int GetRasterDecoderId() const = 0;
};

}  // namespace gpu

#endif  // GPU_COMMAND_BUFFER_SERVICE_DECODER_CONTEXT_H_
